-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Execution tracing: GraphQL query to get storage inputs for past blocks #2491
base: master
Are you sure you want to change the base?
Conversation
8d80d7b
to
3ba2bc7
Compare
- Related to #1432 # Release notes In this release, we: - Changed `ABIDecoder` methods to take `std::io::Read` instead of `&[u8]`, allowing it to be used in a streaming manner. # Summary `ABIDecoder` methods take `bytes: impl std::io::Read` instead of `bytes: &[u8]`. This allows decoding abi types without having to know the size in advance. This is particularly useful when reading them directly from VM memory, which will be used by the indexer after FuelLabs/fuel-core#2491 is done. # Breaking Changes `ABIDecoder` methods take `bytes: impl std::io::Read` instead of `bytes: &[u8]`. Callers using arrays or `Vec` must change the argument from `&value` to `value.as_slice()`. # Checklist - [x] All **changes** are **covered** by **tests** (or not applicable) - [x] All **changes** are **documented** (or not applicable) - [x] I **reviewed** the **entire PR** myself (preferably, on GH UI) - [x] I **described** all **Breaking Changes** (or there's none) --------- Co-authored-by: hal3e <[email protected]> Co-authored-by: Ahmed Sagdati <[email protected]> Co-authored-by: segfault-magnet <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good integration with database types ! Liked it !
crates/fuel-core/src/schema/tx.rs
Outdated
ctx: &Context<'_>, | ||
height: U32, | ||
) -> async_graphql::Result<Vec<StorageReadReplayEvent>> { | ||
let config = ctx.data_unchecked::<GraphQLConfig>().clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let config = ctx.data_unchecked::<GraphQLConfig>().clone(); | |
let config = ctx.data_unchecked::<GraphQLConfig>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -702,6 +702,114 @@ where | |||
Ok(()) | |||
} | |||
|
|||
#[tracing::instrument(skip_all)] | |||
fn record_storage_reads_for<D>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is never called in the code. Isn't it supposed to be called here ? Or it's outdated ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hahahaha I already managed to refactor that code out. Nice. I'll remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I would vouch for an indepedent flag that can be enabled by default when we use debug but that could be enabled by himself also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've read a lot more, but I'm still WIP with my review. Will add more feedback.
bin/fuel-core/src/cli/run/graphql.rs
Outdated
/// Query costs for generating execution trace for a block.® | ||
#[clap( | ||
long = "query-cost-storage-read-replay", | ||
default_value = DEFAULT_QUERY_COSTS.storage_read_replay.to_string(), | ||
env | ||
)] | ||
pub storage_read_replay: usize, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The verbiage around this isn't clear to me.
This argument is for setting the costs? I think more context is required here and perhaps a more specific name for the field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It's a filed in a struct called QueryCosts
, and all other arguments have similar purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ah ah. I remember this now. I suggested on another PR that we should rename this to "Complexity" or something (just because we already have concepts of gas costs etc). I won't nitpick too much on this since at least it's within the graphql
crate, but giving some clarity in the comment on what types of costs this is would be valuable (even if the other args aren't that clear).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good overall. I add a few easy-to-fix comments.
One thing I'd like to call out is there doesn't seem to be any UTs for the new behavior. I feel like they would be relatively easy to add and would push things left a bit.
tests/tests/storage_read_replay.rs
Outdated
/// Create a counter contract. | ||
/// Increment it multiple times, and make sure the replay gives correct storage state every time. | ||
#[tokio::test(flavor = "multi_thread")] | ||
async fn test_storage_read_replay_returns_counter_state() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like tests like this a lot. It's easy to read since the helpers make_counter_contract
and increment_counter
are very declarative.
It also gives an example of how the chain can be used as you're actually deploying something and interacting with it. Eventually, I want a whole testing framework like this for deploying Sway contracts inside of tests--not for integ tests, but for dApp tests.
use fuel_core_types::fuel_types::BlockHeight; | ||
|
||
#[test] | ||
fn execution_trace_block_tx_gql_output() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to specify that this is a compatibility regression/snapshot test. I don't get anything from this test name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have loads of *_gql_output
tests that do this. Should those all be renamed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(changed the method name to match storage_read_replay
in fc097bf, as that's what the feature is now called)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have loads of *_gql_output tests that do this. Should those all be renamed?
Not your responsibility. I don't think upholding the precedence gains us anything here. I'd prefer clear names wherever possible.
Taking this back to draft until #2661 is merged, as I want to refactor this on top of it. |
Description
To support local debugging and execution tracing, we need to add an API that returns the state that VM needs to execute transactions. This is done by recording all database accesses during tx validation, called storage read replay (bikeshedding in progress). This data is then exposed as-is through GraphQL. The API is non-trivial to consume, but a seperate client is proviced, see https://github.com/FuelLabs/execution-trace
The implementation exposes database table names and representations directly. Maintaining backwards compatibility with this could turn out to be quite hard.
Follow-ups:
Example query:
TODO
--debug
flag to--historical-execution
(see Dry run in the past #2661)Open questions:
--debug
flag to enabled this, as opposed to super-high query cost or a separate flag to enable?Checklist
Before requesting review
After merging, notify other teams
See the VM PR FuelLabs/fuel-vm#881.